/*
 *--------------------------------------------------------------------------
 *   Battlefield - A Realtime Network Multiplayer Game
 *   =======================================================
 *   Developed by Group D02 - 2009/2010 Semester 4 - CS2103
 *     Harry Nguyen Duy Hoang <nnduyhoang@yahoo.co.uk>
 *     Kent Chng Siang Rong <fivefootway@gmail.com>
 *     Lim Yong Peng <limpeng1986@gmail.com>
 *     Loh Xiankun <u0807185@nus.edu.sg>
 *   Instructed by
 *     Dr. Damith C.Rajapakse <damith@gmail.com>
 *   =======================================================
 *   $Id: WarPhaseScreen.java 662 2010-07-30 08:49:22Z Harry $
 *   $LastChangedDate: 2010-07-30 08:49:22 +0000 (Fri, 30 Jul 2010) $
 *   $LastChangedBy: Harry $
 *--------------------------------------------------------------------------
 */
package battlefield.ui.screen;

import battlefield.resource.Graphics;
import battlefield.resource.Sounds;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import battlefield.entity.Unit;
import battlefield.entity.UnitModel;
import battlefield.resource.Music;
import battlefield.state.UnitType;
import battlefield.ui.component.InventoryButton;
import battlefield.ui.component.InventoryPanel;
import battlefield.ui.component.MapButton;
import battlefield.ui.component.MapPanel;
import battlefield.ui.component.MessagePanel;
import battlefield.ui.component.MissionButton;
import battlefield.ui.component.MissionPanel;
import battlefield.ui.component.StatusPanel;
import battlefield.ui.component.GameTabPane;
import battlefield.util.ExceptionUtils;
import java.awt.Dimension;
import java.rmi.RemoteException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.ArrayList;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.Timer;

/**
 *
 * @author Kent
 */
public class WarPhaseScreen extends Screen implements ActionListener {

    MapPanel playerMapPanel, opponentMapPanel;
    InventoryPanel inventoryPanel;
    StatusPanel statusPanel;
    MessagePanel msgPanel;
    GameTabPane tabbedPane;
    MissionPanel missionPanel;
    private UnitType selectedUnitType;
    Timer mapTimer, reloadWeaponsTimer, missionTimer;
    int goldReloadSeconds, reloadCounter;

    public WarPhaseScreen() {
        initComponents();
    }

    private void initComponents() {

        try {
            getLogic().createMissions(getPlayer().getId());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        try {
            goldReloadSeconds = getGame(true).getGoldReloadDuration();
            reloadCounter = goldReloadSeconds;
            ArrayList<UnitModel> models = new ArrayList<UnitModel>();
            for (UnitModel model : getLogic().getUnitModels()) {
                if (model.getType() == UnitType.WEAPON || model.getType() == UnitType.EQUIPMENT) {
                    models.add(model);
                }
            }
            inventoryPanel = new InventoryPanel(models);
        } catch (RemoteException ex) {
            JOptionPane.showMessageDialog(this, ExceptionUtils.getMessage(ex));
        }
        playerMapPanel = new MapPanel(getPlayer(true).getMap(), true);
        opponentMapPanel = new MapPanel(getOpponent(true).getMap(), false);
        statusPanel = new StatusPanel(getPlayer(), getOpponent());
        msgPanel = new MessagePanel();
        missionPanel = new MissionPanel(getPlayer());
        tabbedPane = new GameTabPane(JTabbedPane.LEFT, JTabbedPane.WRAP_TAB_LAYOUT);

        playerMapPanel.setPreferredSize(new Dimension(448, 448));
        opponentMapPanel.setPreferredSize(new Dimension(448, 448));
        inventoryPanel.setPreferredSize(new Dimension(800, 180));
        inventoryPanel.setSize(new Dimension(800, 180));
        statusPanel.setPreferredSize(new Dimension(450, 41));
        msgPanel.setPreferredSize(new Dimension(450, 41));
        tabbedPane.addTab("", inventoryPanel);
        tabbedPane.addTab("", missionPanel);
        tabbedPane.setTabComponentAt(0, new JLabel(new ImageIcon(Graphics.TAB_TITLE_INVENTORY.getImage())));
        tabbedPane.setTabComponentAt(1, new JLabel(new ImageIcon(Graphics.TAB_TITLE_MISSION.getImage())));
        tabbedPane.setPreferredSize(new Dimension(880, 200));

        playerMapPanel.addActionListener(this, "MY_MAP_CELL_CLICK");
        opponentMapPanel.addActionListener(this, "OPPONENT_MAP_CELL_CLICK");
        inventoryPanel.addActionListener(this, "SELECT_UNIT");
        missionPanel.addActionListener(this, "MISSION_BUTTON");

        GroupLayout layout = new GroupLayout(this);
        this.setBackgroundImage(Graphics.BACKGROUND_MAIN.getImage());
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        layout.setHorizontalGroup(
                layout.createSequentialGroup().addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER).addGroup(layout.createSequentialGroup().addComponent(statusPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent(msgPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)).addGroup(layout.createSequentialGroup().addComponent(playerMapPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent(opponentMapPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)).addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)));
        layout.setVerticalGroup(
                layout.createSequentialGroup().addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER).addComponent(statusPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent(msgPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)).addGroup(layout.createParallelGroup().addComponent(playerMapPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent(opponentMapPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)).addComponent(tabbedPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE));


        mapTimer = new Timer(2000, this);
        mapTimer.start();

        reloadWeaponsTimer = new Timer(1000, this);
        reloadWeaponsTimer.start();

        missionTimer = new Timer(5000, this);

        try {
            getLogic().beginWarPhase(getPlayer().getId());
        } catch (RemoteException ex) {
            JOptionPane.showMessageDialog(this, ExceptionUtils.getMessage(ex));
        }

        inventoryPanel.update();
        updateStatus();

        if (Music.LOADING.isRunning()) {
            Music.LOADING.stop();
        }
        if (!Music.WAR_PHASE.isRunning()) {
            Music.WAR_PHASE.start();
        }
    }

    /* Begin Region: State Pattern */
    @Override
    public Screen win() {
        stopTimers();
        this.removeAll();
        return new GameOverScreen(true);
    }

    @Override
    public Screen lose() {
        stopTimers();
        this.removeAll();
        return new GameOverScreen(false);
    }
    /* End Region: State Pattern */

    public UnitType getSelectedUnitType() {
        return selectedUnitType;
    }

    public void setSelectedUnitType(UnitType selectedUnitType) {
        this.selectedUnitType = selectedUnitType;
    }

    private void updateStatus() {
        try {
            getLogic().updateUnitCounts(getPlayer().getId());
            getLogic().updateUnitCounts(getOpponent().getId());
            statusPanel.update(getPlayer(true), getOpponent(true));
        } catch (RemoteException ex) {
            Logger.getLogger(WarPhaseScreen.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void stopTimers() {
        mapTimer.stop();
        reloadWeaponsTimer.stop();
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(mapTimer)) {
            try {
                playerMapPanel.update(getPlayer(true).getMap());
                if (!getLogic().isAlive(getPlayer().getId())) {
                    getGUI().lose();
                }
            } catch (RemoteException ex) {
                stopTimers();
                msgPanel.updateMessage(ExceptionUtils.getMessage(ex));
                //JOptionPane.showMessageDialog(this, ExceptionUtils.getMessage(ex));
            }
            updateStatus();
        } else if (e.getSource().equals(reloadWeaponsTimer)) {

            reloadCounter--;
            if (reloadCounter == 0) {
                statusPanel.getTimer().setText("Reloading Gold");
                try {
                    getLogic().topupGold(getPlayer().getId(), getGame().getGoldReloadAmount());
                } catch (RemoteException ex) {
                    stopTimers();
                    msgPanel.updateMessage(ExceptionUtils.getMessage(ex));
                    //JOptionPane.showMessageDialog(this, ExceptionUtils.getMessage(ex));
                }
                reloadCounter = goldReloadSeconds;
                statusPanel.getTimer().setText(reloadCounter + " seconds to reload");
                updateStatus();
            } else {
                statusPanel.getTimer().setText(reloadCounter + " seconds to reload");
            }

            inventoryPanel.update();
        } else if (e.getSource().equals(missionTimer)) {
            try {
                missionTimer.stop();
                missionPanel.updateMissions(getPlayer(true));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } else if (e.getActionCommand().equals("SELECT_UNIT")) {
            InventoryButton button = (InventoryButton) e.getSource();
            UnitModel model = button.getUnitModel();
            if (model.getType().equals(UnitType.EQUIPMENT)) {
                playerMapPanel.setPreviewUnit(new Unit(0, model));
                opponentMapPanel.setPreviewUnit(null);
            } else if (model.getType().equals(UnitType.WEAPON)) {
                opponentMapPanel.setPreviewUnit(new Unit(0, model));
                playerMapPanel.setPreviewUnit(null);
            }

        } else if (e.getActionCommand().equals("OPPONENT_MAP_CELL_CLICK")) {
            Unit previewUnit = opponentMapPanel.getPreviewUnit();

            if (previewUnit == null) {
                return;
            }
            UnitModel model = previewUnit.getModel();

            try {
                MapButton button = (MapButton) e.getSource();
                if (getLogic().buyAndUseWeaponOnMap(getPlayer().getId(), getOpponent().getId(), model.getId(), button.getRow(), button.getColumn())) {
                    Sounds.BOMB_HIT.play();
                    ArrayList<Unit> destroyedUnits = new ArrayList<Unit>();
                    for (int i = 0; i < model.getRows(); i++) {
                        for (int j = 0; j < model.getColumns(); j++) {
                            if (model.hasCellAt(i, j)) {
                                Unit unit = getLogic().getUnitOnMap(getOpponent().getId(), button.getRow() + i, button.getColumn() + j);
                                if (unit != null && unit.isDestroyed() && !destroyedUnits.contains(unit)) {
                                    destroyedUnits.add(unit);
                                }
                            }
                        }
                    }

                    for (Unit unit : destroyedUnits) {
                        opponentMapPanel.revealDestroyedUnit(unit);
                    }
                } else {
                    Sounds.BOMB_MISS.play();
                }
                opponentMapPanel.update(getOpponent(true).getMap());
                inventoryPanel.update();
                updateStatus();
                if (!getLogic().isAlive(getOpponent().getId())) {
                    getGUI().win();
                }

            } catch (RemoteException ex) {
                Sounds.ERROR.play();
                msgPanel.updateMessage(ExceptionUtils.getMessage(ex));
                //JOptionPane.showMessageDialog(this, ExceptionUtils.getMessage(ex));
            }

        } else if (e.getActionCommand().equals("MY_MAP_CELL_CLICK")) {
            Unit previewUnit = playerMapPanel.getPreviewUnit();

            if (previewUnit == null) {
                return;
            }
            UnitModel model = previewUnit.getModel();

            try {
                MapButton button = (MapButton) e.getSource();
                updateStatus();
                playerMapPanel.update(getPlayer(true).getMap());
                if (!getLogic().isAlive(getPlayer().getId())) {
                    getGUI().lose();
                }
                getLogic().buyAndPlaceUnitOnMap(getPlayer().getId(), playerMapPanel.getPreviewUnit().getModel().getId(), button.getRow(), button.getColumn());
                Sounds.MOUSE_CLICK.play();
                playerMapPanel.update(getPlayer(true).getMap());
                inventoryPanel.update();
                updateStatus();

            } catch (RemoteException ex) {
                msgPanel.updateMessage(ExceptionUtils.getMessage(ex));
                Sounds.ERROR.play();
                //JOptionPane.showMessageDialog(this, ExceptionUtils.getMessage(ex));
            }

        } else if (e.getActionCommand().equals("MISSION_BUTTON")) {
            MissionButton selectedButton = (MissionButton) e.getSource();
            selectedButton.setEnabled(false);
            selectedButton.setText("<html><center><font color='red'>In Progress.....</font></center></html>");
            try {
                int gold = getLogic().doMission(getPlayer().getId(), selectedButton.getName());
                getLogic().topupGold(getPlayer().getId(), gold);

                missionTimer.start();

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    }

    @Override
    protected void finalize() throws Throwable {

        if (mapTimer != null && mapTimer.isRunning()) {
            mapTimer.stop();
        }
        mapTimer = null;

        if (reloadWeaponsTimer != null && reloadWeaponsTimer.isRunning()) {
            reloadWeaponsTimer.stop();
        }
        reloadWeaponsTimer = null;

        if (missionTimer != null && missionTimer.isRunning()) {
            missionTimer.stop();
        }
        missionTimer = null;

        super.finalize();
    }
}
